﻿using AADoubleFive.model;
using AADoubleFive.utils;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO.Ports;
using System.Text;
using System.Windows;
using System.Windows.Media.Imaging;


namespace AADoubleFive
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        SerialPortUtil serialPortUtil;

        private MainWindowViewModel windowViewModel;
        public MainWindow()
        {
            InitializeComponent();

            windowViewModel = new MainWindowViewModel();
            this.DataContext = windowViewModel;

            this.btnOpen.Click += new RoutedEventHandler(Open_Click);
            this.btnSend.Click += new RoutedEventHandler(Send_Click);

            this.Closing += new CancelEventHandler(Windows_Closing);

            serialPortUtil = new SerialPortUtil();

            Log.SetTextControl(logger);
        }

        private void Windows_Closing(object sender, CancelEventArgs e)
        {
            if (serialPortUtil.IsOpen)
            {
                serialPortUtil.ClosePort();
            }
        }

        private void Open_Click(object sender, RoutedEventArgs e)
        {
            if (!windowViewModel.isOpen)
            {
                if (serialPortUtil.IsOpen)
                {
                    serialPortUtil.ClosePort();
                }
                if (windowViewModel.selectedPortName == null)
                {
                    MessageBox.Show(this,"未检测到串口，请查看串口连接是否正确","错误",MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                serialPortUtil.SetPortName(windowViewModel.selectedPortName.name);
                serialPortUtil.SetBaudRate((SerialPortBaudRates)windowViewModel.selectedBaudRate.value);
                try
                {
                    serialPortUtil.OpenPort();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }


                windowViewModel.isOpen = true;
                ImageControl.Source = new BitmapImage(new Uri("pack://application:,,,/image/link.png"));

                if (serialPortUtil.IsOpen)
                {
                    serialPortUtil.DataReceivedEvent += SerialPortRevFunc;
                    Log.Suc("串口（{0}）打开成功", windowViewModel.selectedPortName.name);
                    
                }
            }
            else{
                if (serialPortUtil.IsOpen)
                {
                    serialPortUtil.ClosePort();
                    serialPortUtil.DataReceivedEvent -= SerialPortRevFunc;
                }

                if (!serialPortUtil.IsOpen)
                {
                    Log.Info("串口（{0}）已关闭", windowViewModel.selectedPortName.name);                 
                }

                windowViewModel.isOpen = false;
                ImageControl.Source = new BitmapImage(new Uri("pack://application:,,,/image/unlink.png"));
            }

        }

        private void SerialPortRevFunc(byte[] ReceivedData)
        {
            string hex = CommunicationHelper.Byte2HexStr(ReceivedData);
            Log.Info(hex);

            if (ReceivedData.Length == 20)
            {
                byte errflag = ReceivedData[17];

                StringBuilder sb = new StringBuilder();
                // 脉宽错误
                if((errflag & (byte)(1)) != 0)
                {
                    sb.Append("脉宽错误").Append("、");
                }
                // 相位分频错误
                if((errflag & (byte)(1 << 1)) != 0)
                {
                    sb.Append("相位分频错误").Append("、");
                }
                // 采集总个数错误
                if ((errflag & (byte)(1 << 2)) != 0)
                {
                    sb.Append("采集总个数错误").Append("、");
                }
                // 平均次数错误
                if ((errflag & (byte)(1 << 3)) != 0)
                {
                    sb.Append("平均次数错误").Append("、");
                }
                // 上次采集没有完成
                if ((errflag & (byte)(1 << 4)) != 0)
                {
                    sb.Append("上次采集没有完成").Append("、");
                }

                if (sb.Length > 0)
                {
                    sb.Length--;
                    Log.Error(sb.ToString());
                }
            }

        }

        private void Send_Click(object sender, RoutedEventArgs e)
        {
            if (!serialPortUtil.IsOpen)
            {
                Log.Error("发送失败，串口（{0}）已关闭，请重新打开。", windowViewModel.selectedPortName.name);
                return;
            }


            byte[] buffer = new byte[1024];
            int length = MakeMsgData(ref buffer);
            serialPortUtil.WriteData(buffer, 0, length);

            //byte[] recvBuffer = new byte[20];
            //serialPortUtil.SendCommand(buffer, ref recvBuffer, 2000);
            //SerialPortRevFunc(recvBuffer);
        }

        private int MakeMsgData(ref byte[] buffer)
        {
            int pulseWidth = windowViewModel.selectedPulseWidth.value;
            int freDivNum = windowViewModel.selectedFreDivNum.value;
            int phaseShiftNum = windowViewModel.selectedPhaseShiftNum.value;
            int adcNumber = windowViewModel.adcNumber;
            int averageNum = windowViewModel.averageNum;

            int offset = 0;

            buffer[offset] = 0xAA; offset += 1;
            buffer[offset] = 0x55; offset += 1;

            // 4字节预留
            offset += 4;

            // 脉宽
            byte[] byteValue = BitConverter.GetBytes((short)pulseWidth);
            //Array.Copy(byteValue, 0, buffer, offset, 2);
            //offset += 2;
            buffer[offset] = byteValue[1]; offset += 1;
            buffer[offset] = byteValue[0]; offset += 1;

            // 相位分频数 高位预留
            offset += 1;
            if(rbFreDivNum.IsChecked == true)
            {
                // 相位分频数 低位
                buffer[offset] = (byte)freDivNum; offset += 1;
            }
            else if(rbPhaseShiftNum.IsChecked == true)
            {
                // 相位移动数 低位
                buffer[offset] = (byte)phaseShiftNum; offset += 1;
            }


            // 采集深度
            byteValue = BitConverter.GetBytes((short)adcNumber);
            //Array.Copy(byteValue, 0, buffer, offset, 2);
            //offset += 2;
            buffer[offset] = byteValue[1]; offset += 1;
            buffer[offset] = byteValue[0]; offset += 1;

            // 平均次数
            byteValue = BitConverter.GetBytes(averageNum);
            //Array.Copy(byteValue, 0, buffer, offset, 4);
            //offset += 4;
            buffer[offset] = byteValue[3]; offset += 1;
            buffer[offset] = byteValue[2]; offset += 1;
            buffer[offset] = byteValue[1]; offset += 1;
            buffer[offset] = byteValue[0]; offset += 1;

            // 2字节预留
            offset += 2;

            buffer[offset] = 0x5A; offset += 1;
            buffer[offset] = 0xA5; offset += 1;


            return offset;
        }
    }

    public class MainWindowViewModel :ViewModelBase
    {
        public MainWindowViewModel()
        {
            isOpen = false;

            #region 串口号
            portNames = new ObservableCollection<ItemViewModel>();
            string[] ports = SerialPortUtil.GetPortNames();
            foreach (string port in ports)
            {
                ItemViewModel portItem = new ItemViewModel();
                portItem.name = port;
                portNames.Add(portItem);
            }
            if(portNames.Count > 0)
            {
                selectedPortName = portNames[0];
            }
            #endregion

            #region 波特率
            baudRates = new ObservableCollection<ItemViewModel>();
            ItemViewModel baudRate = new ItemViewModel();
            baudRate.name = "110";
            baudRate.value = 110;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "300";
            baudRate.value = 300;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "600";
            baudRate.value = 600;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "1200";
            baudRate.value = 1200;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "2400";
            baudRate.value = 2400;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "4800";
            baudRate.value = 4800;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "9600";
            baudRate.value = 9600;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "14400";
            baudRate.value = 14400;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "19200";
            baudRate.value = 19200;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "38400";
            baudRate.value = 38400;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "56000";
            baudRate.value = 56000;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "57600";
            baudRate.value = 57600;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "115200";
            baudRate.value = 115200;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "128000";
            baudRate.value = 128000;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "230400";
            baudRate.value = 230400;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "256000";
            baudRate.value = 256000;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "460800";
            baudRate.value = 460800;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "921600";
            baudRate.value = 921600;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "1000000";
            baudRate.value = 1000000;
            baudRates.Add(baudRate);
            baudRate = new ItemViewModel();
            baudRate.name = "2000000";
            baudRate.value = 2000000;
            baudRates.Add(baudRate);

            selectedBaudRate = baudRates[12];
            #endregion

            #region 脉宽
            pulseWidths = new ObservableCollection<ItemViewModel>();
            ItemViewModel pulseWidth = new ItemViewModel();
            pulseWidth.name = "5ns";
            pulseWidth.value = 5;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "10ns";
            pulseWidth.value = 10;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "25ns";
            pulseWidth.value = 25;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "50ns";
            pulseWidth.value = 50;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "100ns";
            pulseWidth.value = 100;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "250ns";
            pulseWidth.value = 250;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "500ns";
            pulseWidth.value = 500;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "1us";
            pulseWidth.value = 1000;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "10us";
            pulseWidth.value = 10000;
            pulseWidths.Add(pulseWidth);
            pulseWidth = new ItemViewModel();
            pulseWidth.name = "20us";
            pulseWidth.value = 20000;
            pulseWidths.Add(pulseWidth);

            selectedPulseWidth = pulseWidths[1];
            #endregion

            #region 相位分频数
            freDivNums = new ObservableCollection<ItemViewModel>();
            ItemViewModel freDiv = new ItemViewModel();
            freDiv.name = "1";
            freDiv.value = 1;
            freDivNums.Add(freDiv);
            freDiv = new ItemViewModel();
            freDiv.name = "2";
            freDiv.value = 2;
            freDivNums.Add(freDiv);
            freDiv = new ItemViewModel();
            freDiv.name = "4";
            freDiv.value = 4;
            freDivNums.Add(freDiv);
            freDiv = new ItemViewModel();
            freDiv.name = "8";
            freDiv.value = 8;
            freDivNums.Add(freDiv);
            freDiv = new ItemViewModel();
            freDiv.name = "16";
            freDiv.value = 16;
            freDivNums.Add(freDiv);

            selectedFreDivNum = freDivNums[0];
            #endregion

            #region 相位移动数
            phaseShiftNums = new ObservableCollection<ItemViewModel>();
            for(int i = 0; i < 16; i++)
            {
                ItemViewModel phaseShiftNum = new ItemViewModel();
                phaseShiftNum.name = i.ToString();
                phaseShiftNum.value = i;
                phaseShiftNums.Add(phaseShiftNum);
            }
            selectedPhaseShiftNum = phaseShiftNums[0];
            #endregion

            adcNumber = 8192;
            averageNum = 1024;
        }

        private bool m_isOpen;
        public bool isOpen
        {
            get { return m_isOpen; }
            set
            {
                m_isOpen = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<ItemViewModel> m_portNames;
        public ObservableCollection<ItemViewModel> portNames
        {
            get { return m_portNames; }
            set
            {
                m_portNames = value;
                NotifyPropertyChanged();
            }
        }

        private ItemViewModel m_selectedPortName;
        public ItemViewModel selectedPortName
        {
            get { return m_selectedPortName; }
            set
            {
                m_selectedPortName = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<ItemViewModel> m_baudRates;
        public ObservableCollection<ItemViewModel> baudRates
        {
            get { return m_baudRates; }
            set
            {
                m_baudRates = value;
                NotifyPropertyChanged();
            }
        }

        private ItemViewModel m_selectedBaudRate;
        public ItemViewModel selectedBaudRate
        {
            get { return m_selectedBaudRate; }
            set
            {
                m_selectedBaudRate = value;
                NotifyPropertyChanged();
            }
        }

        private  ObservableCollection<ItemViewModel> m_pulseWidths;
        public ObservableCollection<ItemViewModel> pulseWidths
        {
            get { return m_pulseWidths; }
            set
            {
                m_pulseWidths = value;
                NotifyPropertyChanged();
            }
        }

        private ItemViewModel m_selectedPulseWidth;
        public ItemViewModel selectedPulseWidth
        {
            get { return m_selectedPulseWidth; }
            set
            {
                m_selectedPulseWidth = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<ItemViewModel> m_freDivNums;
        public ObservableCollection<ItemViewModel> freDivNums
        {
            get { return m_freDivNums; }
            set
            {
                m_freDivNums = value;
                NotifyPropertyChanged();
            }
        }

        private ItemViewModel m_selectedFreDivNum;
        public ItemViewModel selectedFreDivNum
        {
            get { return m_selectedFreDivNum; }
            set
            {
                m_selectedFreDivNum = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<ItemViewModel> m_phaseShiftNums;
        public ObservableCollection<ItemViewModel> phaseShiftNums
        {
            get { return m_phaseShiftNums; }
            set
            {
                m_phaseShiftNums = value;
                NotifyPropertyChanged();
            }
        }

        private ItemViewModel m_selectedPhaseShiftNum;
        public ItemViewModel selectedPhaseShiftNum
        {
            get { return m_selectedPhaseShiftNum; }
            set
            {
                m_selectedPhaseShiftNum = value;
                NotifyPropertyChanged();
            }
        }

        private int m_adcNumber;
        public int adcNumber
        {
            get { return m_adcNumber; }
            set
            {
                m_adcNumber = value;
                NotifyPropertyChanged();
            }
        }

        private int m_averageNum;
        public int averageNum
        {
            get { return m_averageNum; }
            set
            {
                m_averageNum = value;
                NotifyPropertyChanged();
            }
        }
    }
}
